spb/datacenterindex
Public
HTML 53.9%
TypeScript 44.5%
JavaScript 0.6%
SQL 0.5%
1"use client";23import type { CountryDetail } from "@dci/core";4import { AreaChart } from "@/components/ui/charts";5import { EmptyState } from "@/components/ui/states";6import { fmtInt, fmtMw } from "@/lib/format";78/**9 * Facilities over time (cumulative count by opening year) and, when published, cumulative known MW.10 * Rendered as two single-axis charts (never dual-axis): MW only when at least two years carry a figure.11 */12export function GrowthChart({ data }: { data: CountryDetail["growth"] }) {13 const rows = [...data].filter((d) => Number.isFinite(d.year)).sort((a, b) => a.year - b.year);14 if (rows.length < 2) return <EmptyState compact title="Not enough dated openings" description="Growth charts appear once at least two opening years are published for facilities in this country." />;15 // fill the years between the first and last observation so the curve is continuous16 const first = rows[0]!.year;17 const last = Math.max(rows[rows.length - 1]!.year, new Date().getUTCFullYear());18 const byYear = new Map(rows.map((r) => [r.year, r]));19 const facilities: Array<{ x: number; y: number }> = [];20 const mw: Array<{ x: number; y: number | null }> = [];21 let cumMw: number | null = null;22 let hasMwYears = 0;23 for (let y = first; y <= last; y++) {24 const r = byYear.get(y);25 // API rows are already cumulative facility counts by opening year26 const prevF = facilities.length ? facilities[facilities.length - 1]!.y : 0;27 facilities.push({ x: y, y: r ? Math.max(prevF, r.facilities) : prevF });28 if (r && r.knownMw !== null) {29 cumMw = (cumMw ?? 0) + r.knownMw;30 hasMwYears++;31 }32 mw.push({ x: y, y: cumMw });33 }34 const span = facilities.length;35 const step = span > 40 ? 5 : span > 20 ? 2 : 1;36 const thin = <T extends { x: number }>(pts: T[]) => pts.filter((p, i) => i === pts.length - 1 || (p.x - first) % step === 0);37 return (38 <div className="grid gap-6 md:grid-cols-2">39 <div>40 <div className="label-caps mb-2">Facilities (cumulative, by opening year)</div>41 <AreaChart series={[{ name: "Facilities", data: thin(facilities), color: "var(--ink)" }]} height={180} format={(v) => fmtInt(v)} ariaLabel="Cumulative facilities by opening year" />42 </div>43 <div>44 <div className="label-caps mb-2">Known MW (cumulative, published figures)</div>45 {hasMwYears >= 2 ? (46 <AreaChart series={[{ name: "Known MW", data: thin(mw), color: "var(--accent)" }]} height={180} format={(v) => fmtMw(v)} ariaLabel="Cumulative known capacity by opening year" />47 ) : (48 <EmptyState compact title="MW not published by year" description="Operators in this country have not published enough dated capacity figures to chart." />49 )}50 </div>51 </div>52 );53}54